/*
* The model of block.
*/
function BlockModel(id, content, noteId){
    // block id
    this.id = id;    
    
    // block content
    this.content = content;     
    
    // note id
    this.noteId = noteId; 
}

/*
* The enum of block status.
*/
var BlockStatus = {
    // view status
    View: 0,
    
    // edit status
    Edit: 1
};

/*
* The Block is inherited from BaseClass.
*/
Block.prototype = new BaseClass;

/*
* Constructor that creates a new object for the Block.
* @param  blockModel | BlockModel | the  block model, that is BlockModel class.
*/
function Block(blockModel){    
    var _blockModel = blockModel; // block model

    var _status = BlockStatus.View; // view status by default

    var _isChecked = false; // if the block is checked, false by default

    var _hasElement = false; //  check if the block element is created or not 
    
    // private function
    var _context = function($newContext){
        if($newContext == undefined){
            return $('body'); // default context for block
        }else{
            return $newContext;
        }
    };

    var _validateContext = function($context){
        if($context == undefined){
            throw "Required parameter: $context";
        }

        if(typeof $context != 'object'){
            throw "$context should be object type"
        }
    }

    var _getCheckboxHtml = function(){
        var template = "<input type='checkbox'>"
    }
    
    var _getBlockHtml = function($this){
        var template = "<pre data-blockid='{{id}}'>{{content}}</pre>";

        var htmlString = $this.buildHtml(template, _blockModel);

        return htmlString;
    }

    // get current block jquery object
    var _getBlockJQuery = function($this)
    {
        return $(_getBlockHtml($this));
    }

    // get the block's jQuery object
    var _getBlockObject = function($context){
        var $blockObject = $('pre[data-blockid=' + _blockModel.id + ']', $context);

        return $blockObject;
    }

    // check if there is the block tag, that is "<pre>xxx<pre>", in the page.
    var _hasBlockTag = function($this, $context){
        // variables
        var hasBlockTag = false;

        var $blockObject = _getBlockObject($context);

        // call super class method to check if the $blockObject has children or not
        if($this.isValidObject($blockObject))
            hasBlockTag = true;

        return hasBlockTag;
    }
    
    var _setStatus = function(statusValue){
        if(statusValue < 0 || statusValue >1)
             throw "Parameter: statusValue should be BlockStatus value. That is BlockStatus.View or BlockStatus.Edit.";
             
        if(statusValue == BlockStatus.View){
            
        }else{
            
        }
        
        _status = statusValue;
    }
    
    /*
    * Add the block. This will create block tag, like "<pre>xxx</pre>", the block tag is added to $parent.
    * @param $context | jQuery | Required | the parent element the block tag will be added to, like $('body')
    * @param indexToAdd | Int | Optional | the index of parent the block will be added to
    *        i.e, indexToAdd = 2, and then the block will be added as the 3rd element
    *        if this param is undefined, it will append the block(Append means as the last element)
    * @return Boolean | true == { Showed successfully }, false == { Failed to add block element }
    */
    this.add = function($context, indexToAdd){
        // variables
        var isSuccess = false;

        // validation
        _validateContext($context);

        // make sure the indexToAdd value is valid
        if(indexToAdd > $context.children().length){
            throw "Error: indexToAdd(" + indexToAdd + ") is greater than the length(" + $context.children().length + ") of children in $context";
        }
        
        var htmlString = _getBlockHtml(this)
        if(indexToAdd == undefined){
            $context.append(htmlString);
        }else{
            $(htmlString).insertAfter($context.children().eq(indexToAdd - 1)); 
        }

        // set success
        isSuccess = true;
            
        // flag to record the block element being built
        _hasElement = true;

        return isSuccess;
    };
     
    /*
    * Delete the block from $context. This will delete the block element, that is ""<pre>xxx</pre>"".
    * Note that: It will only delete the html element, if you need to delete the block in array, 
    * you should delete it yourself by calling array.
    * @param $context | jQuery | Required | the parent element which includes all the block tags, such as $('body')
    * @return Boolean | true == { Deleted successfully }, false == { Failed to delete }
    */
    this.delete = function($context){
        // variables
        var isSuccess = false;

        // validation
        _validateContext($context);

        // get the block subject to be removed from page
        var $deletingBlock = _getBlockObject($context);

        // check if there is the block
        if($deletingBlock.length > 0){
            $deletingBlock.remove();
            isSuccess = true;
        }else{
            isSuccess = false;
        }
        
        return isSuccess;
    };
    
   /*
    * Get the up-to-date block model in the block.
    * @return BlockModel
    */
    this.getBlockModel = function(){
        return _blockModel;
    };    
        
    /*
    * Show the block. This will show block tag, that is "<pre>xxx</pre>".
    * @param $context | jQuery | Required | the parent element which includes all the block tags, such as $('body')
    * @return Boolean | true == { Showed successfully }, false == { Failed to show }
    */
    this.show = function($context){
        // variables
        var isSuccess = false;

        // validation
        _validateContext($context);

        // get block to show
        var $showingBlock = _getBlockObject($context);

        // check if there is the block tag
        if(_hasBlockTag(this, $context)){
            $showingBlock.show();
            isSuccess = true;
        }else{
            isSuccess = false;
        }

        return isSuccess;
    };
    
   /*
    * Hide the block. This will hide block tag, that is "<pre>xxx</pre>".
    * @param $context | jQuery | Required | the parent element which includes all the block tags, such as $('body')
    * @return Boolean | true == { Showed successfully }, false == { Failed to show }
    */
    this.hide = function($context){
        // variables
        var isSuccess = false;

        // validation
        _validateContext($context);

        // get block to show
        var $showingBlock = _getBlockObject($context);

        // check if there is the block tag
        if(_hasBlockTag(this, $context)){
            $showingBlock.hide();
            isSuccess = true;
        }else{
            isSuccess = false;
        }

        return isSuccess;
    };
    
    /*
    * Check the block. This <checkbox> in the block will be checked. Only the view status can be checked.
    */
    this.getCheck = function(){
        return _isChecked;
    }
    
    /*
    * Check the block. This <checkbox> in the block will be checked. Only the view status can be checked.
    */
    this.setCheck = function(){
        // check if the current block is in the status of editing
        var $block = _getBlockJQuery(this);
        // TODO;

        _isChecked = true;
    }
    
    /*
    * Uncheck the block. This <checkbox> in the block will be unchecked. Only the view status can be unchecked.
    */
    this.setUncheck = function(){
        
    }
    
    /*
    * Toggle the block check status. Only the view status can be checked or unchecked.
    */
    this.toggleCheck = function(){
        if(_isChecked)
            this.setUncheck();
        else
            this.setCheck();
    }
    
    /*
    * Get the block's current status. 
    * @return BlockStatus | Status = { BlockStatus.View, BlockStatus.Edit }
    */
    this.getStatus = function(){
        return _status;
    }
    
    /*
    * Set the block status as view.
    * Note that: If the block element is already in the status of view, and then you call this method, it will do nothing.
    */
    this.setViewStatus = function(){
        _setStatus(BlockStatus.View);
    }
    
    /*
    * Set the block status.
    * Note that: If the block element is already in the status of edit, and then you call this method, it will do nothing.
    */
    this.setEditStatus = function(statusValue){
        _setStatus(BlockStatus.Edit);
    }
    
    /*
    * Toggle the block status between view and edit status.
    */
    this.toggleStatus = function(){
        if(_status == BlockStatus.View){
            _status = BlockStatus.Edit;
        }else{
            _status = BlockStatus.View;
        }
    } 

    /*
    * Toggle the block status between view and edit status.
    * @param blockArray | Array | Required | the array which includes all the block objects, this may come from Note object
    * @return Boolean | true == { Update block array successfully }, false == { Failed to update block array }
    */
    this.updateBlockArray = function(blockArray){

    } 
}

